#include <sys/types.h>          
#include <sqlite3.h>
#include <stdio.h>       
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>  
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <ctype.h>
#include <errno.h>
#include <libgen.h>
#include <poll.h>

#include "logger.h"
//#include "database.c"
//#define  WBUFF "hello zhukaifa\n"
#define ARRAY_SIZE(x)       (sizeof(x)/sizeof(x[0]))
//数组长度定义宏


typedef struct data
{

	char  sn[64];
	char  time[64];
	float temp;
}st_data;
int sqlite_save(sqlite3 *db, char *data_buff);	
static inline void msleep(unsigned long ms);
static inline void print_usage(char *progname)
{
	printf("Usage:%s [option]...\n", progname);

        printf("%s is a socket server program, which used to verify client and echo back string from it\n", progname);
	printf("\n Mandatory arguments to long options are mandatory for short options too:\n");

        printf("-b(daemon)set progname runing on background\n");
 	printf("-p(--port):sepcify server listen port.\n");
	printf("-h(--hellp):print this help information.\n");

	printf("\n Example:%s -b -p 8900\n", progname);
	return ;

}
int socket_server_init(char *listen_ip, int listen_port);

int main(int argc, char **argv)
{
	socklen_t                len;
	int                      daemon_run=0;
	int                      sockfd=-1;
	int                      recive=0;
        struct sockaddr_in   	 servaddr;
        struct sockaddr_in   	 cliaddr;
	int                      clifd;
	int                      errno;
	int                      pid=-8;
	int                      on=1;
	int                      ch=-1;
	struct pollfd            fds_array[1024];
	char                     rbuff[1024];
	fd_set                   rdset;
	int                      listenfd;
	int                      i;
	int                      j;
	int                      found;
	int                      maxfd;
	char                    *progname = NULL;
	int                      serv_port;
	char                    *serv_ip;
        int                      opt;
	int                      max;
        sqlite3                 *db;
        char                    *errmsg;
        char create[]="create table server_pj(ID integer PRIMARY KEY, SN char(10), TIME char(50), TEMP cha(10));";


	struct option                    long_options[] = 

	{

		{"dameon", no_argument, NULL, 'b'},

		{"port", required_argument, NULL, 'p'},

		{"help", no_argument, NULL, 'h'},
	
		{ NULL, 0, NULL, 0}

	};
//serv_ip     =argv[1];
//serv_port   =atoi(argv[2]);

	progname = basename(argv[0]);
                                                           

	while((opt = getopt_long(argc, argv,"bp:h", long_options, NULL)) != -1)//(需要参数再加:);
	{
		switch(opt)
		{
			case 'b':
				daemon_run=1;
				break;

		
			case 'p':
				serv_port=atoi(optarg);//string -> int
				break;
                                  
		
			case 'h':
				print_usage(progname);
				return EXIT_SUCCESS;

			default:
				break;
		}
	}
	if( !serv_port )
	{
		print_usage(progname);
		return -1;
	}

	if ((listenfd=socket_server_init(NULL, serv_port))<0)
	{
	       	printf("ERROR: %s server listen on port %d failure\n", argv[0], serv_port);
		return -2;
	}
	printf("%s server listen on port [%d] successfully!\n", argv[0], serv_port);

	if(daemon_run)//设置程序背景运行
	{
		daemon(0, 0);
	}

	for(i=0; i<ARRAY_SIZE(fds_array); i++)
	{
		fds_array[i].fd=-1;//将素组所有元素（文件描述符）都设为-1说明为空没被占用
	}

	fds_array[0].fd     = listenfd;
	fds_array[0].events = POLLIN;//带数据可读
	max = 0;
       
	if(sqlite3_open("temp_data.db",&db)!=0)
  	{
		perror("cannot open database");
 
	}
        if(sqlite3_exec(db, create, NULL, NULL, &errmsg) != 0)
	{
	    	printf("%s\n", errmsg);

	}

	for( ; ; )//死循环和while(1)一样
	{
		recive = poll(fds_array, max+1, -1);//第三个参数指定等待的毫秒数，-1表示无限超时，0表示立即返回
		if (recive < 0)
		{
			printf("poll failure:%s\n",strerror(errno));
			continue;//结束了本次循环继续下一次循环
		} 
		else if (recive == 0)
		{
			printf("poll get timeout\n:%s", strerror(errno));
			break;//直接结束本次循环《嵌套中break和continue函数比较明显》
       
		}
      
	       	printf("1.poll successfully!!!(如果是第二次打印的话就是更新poll)\n");
   //    if (FD_ISSET(listenfd, &rdset))//调用函数：判断指定文件描述符是否在集合中
	       	if (fds_array[0].revents & POLLIN)//实际发生的事件
		{
			len = sizeof(socklen_t);
			if((clifd=accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0)
			{
			       	printf("accept new client failure:%s\n", strerror(errno));
			       	continue;
			}
		       	printf("2.accept new clifd[%d:%d] successfully\n",clifd, serv_port);
		      	found = 0;
			for(i=0; i<ARRAY_SIZE(fds_array); i++)
			{
				if ( fds_array[i].fd < 0)
				{
					printf("3.accept new client[%d] and add it into arry\n", clifd);
					fds_array[i].fd     = clifd;
				       	fds_array[i].events = POLLIN;
					found = 1;
					break;
				} 
			}
		       	if (! found)
			{
				printf("accept new client[%d] but full, so refuse it\n", clifd);
				close(clifd);
				continue;
		     	}//数组都被clifd填满后跳过found = 0下面的语句，执行if（！found）语句
		      	max = i>max ? i : max;//确保max最大
		}
		else
		{
			for(i=0; i<ARRAY_SIZE(fds_array); i++)
			{
           // if(fds_array[i] < 0 || FD_ISSET(fds_array[i], &rdset))//如果元素为空或者，不在集合中则退出循环。
				if(fds_array[i].fd < 0)
					continue;
			     	if( (recive=read(fds_array[i].fd, rbuff, sizeof(rbuff))) <= 0)
				{
				       	printf("socket[%d] read failure or get disconncet.\n", fds_array[i].fd);
				   	close(fds_array[i].fd);
					fds_array[i].fd = -1;// 发生错误移除该fd
				}
				else 
				{
					printf("4.socket[%d] read get %d bytes data:%s\n", fds_array[i].fd, recive, rbuff);
					if(sqlite_save(db, rbuff) != 0)
					{
						printf("5.sqlite3_save() failure!\n");
						sqlite3_close(db);
					}
					printf("5.sqlite3_save() successfully!\n");
				}
			}
		}
	       	printf("------------------------------------------------------\n");
	}
	sqlite3_close(db);
	close(listenfd);
	return 0;
}

static inline void msleep(unsigned long ms)
{
	struct timeval      tv;
	tv.tv_sec = ms/1000;
	tv.tv_usec = (ms%1000)*1000;

	select(0, NULL, NULL, NULL, &tv);
}




int sqlite_save( sqlite3 *db, char *data_buff)	
{
	
	char          delim[] = "/";
	char         *p = NULL;	
	int           i=0 ;
	char         *data[2];
	char          insert[1024];
	char        **dbresult;
        char         *errmsg;
	int           row=0;
	int           column=0;
	float         temp_data;

	for(p = strtok(data_buff, delim);p != NULL; p = strtok(NULL, delim))
        {
		data[i]=p;
		i++;
	}

	temp_data=atof(data[2]);
	snprintf(insert, sizeof(insert), "insert into server_pj(SN, TIME, TEMP) values('%s', '%s', '%2.2f');", data[0], data[1], temp_data); 


	if(sqlite3_get_table(db, insert, &dbresult, &row, &column, &errmsg) != 0)
	{
	    	printf("insert():%s\n", errmsg);
	}

	return 0;
}

int socket_server_init(char *listen_ip, int listen_port)
{
        struct sockaddr_in       servaddr;
        int                      rv = 0;
        int                      on = 1;
        int                      listenfd;


     	listenfd    = socket(AF_INET, SOCK_STREAM, 0);
	if (listenfd < 0 )
	{
		printf("Use socket() to create a TCP socket failure:%s\n", strerror(errno));
		return -1;
	}
	printf("Creat TCP socket[%d] successfully!!!\n", listenfd);
	setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));//该函数用于实现端口复用

	memset(&servaddr, 0, sizeof(servaddr));
  	servaddr.sin_family      = AF_INET;
 	servaddr.sin_port        = htons(listen_port);//htons将16位主机字节序转换为大端字节序（端口号是16位的）
//    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
//    inet_aton(listen_ip, &servaddr.sin_addr);
        if( !listen_ip )
	{
		servaddr.sin_addr.s_addr =htonl(INADDR_ANY); //htonl将32位主机字节序转换为大端字节序即网络字节序（ip地址是32位）
	}
	else
	{
		if (inet_pton(AF_INET, listen_ip, &servaddr.sin_addr)<=0)
		{
			printf("inet_pton() set listen IP address failure.\n");//pton将点分十进制转换为整数
			rv = -2;
			goto CleanUp;
		}//	inet_aton(servip, &servaddr.sin_addr);//aton将字符串ip地址转换为网络字节序列的IP地址
	}
	rv=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	if (rv < 0) 
	{
		printf("sockfd[%d] bind on  port[%d] failure:%s\n", listenfd, listen_port, strerror(errno));
	    	return -2;
	}

	printf("socket[%d] bind on port[%d] successfully!!!\n", listenfd, listen_port);
	
        if(listen(listenfd, 13) < 0)
        {
       		printf("Use bind() to bind the TCP socket failure: %s\n", strerror(errno));
	    	rv = -4;
		goto CleanUp;
        }
CleanUp:
    if(rv<0)
	close(listenfd);
    else
        rv = listenfd;
	return rv;
}
